package com.atguigu.cloud.common.https.controller;

import com.alibaba.fastjson2.JSONObject;
import com.atguigu.cloud.common.https.entity.CardBasicInfo;
import com.atguigu.cloud.common.https.entity.CardQueryRequest;
import com.atguigu.cloud.common.https.entity.Result;
import com.atguigu.cloud.common.https.entity.TSysSecurity;
import com.atguigu.cloud.common.https.enums.CodeMsgEnum;
import com.atguigu.cloud.common.https.enums.ThirdServiceEnum;
import com.atguigu.cloud.common.https.mapper.TSysSecurityMapper;
import com.atguigu.cloud.common.security.InputValidator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

@Slf4j
@RestController
@RequestMapping("/api/bank")
@RequiredArgsConstructor
public class BankLocationController {
    
    private final TSysSecurityMapper tSysSecurityMapper;
    private final OkHttpClient okHttpClient;
    private final InputValidator inputValidator;
    private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    /**
     * 银行卡归属地查询 V1.0【GET请求】
     * @param cardNumber 银行卡号
     * @return 银行卡基本信息
     */
    @GetMapping("/bankLocationSearch/v1")
    public Result<CardBasicInfo> queryBankLocationV1(@RequestParam("card") String cardNumber) {
        // 输入验证
        if (!StringUtils.hasText(cardNumber)) {
            return Result.error(CodeMsgEnum.PARAM_ERROR, "银行卡号不能为空");
        }
        
        if (!inputValidator.isValidBankCard(cardNumber)) {
            log.warn("无效的银行卡号格式: {}", cardNumber);
            return Result.error(CodeMsgEnum.PARAM_ERROR, "银行卡号格式不正确");
        }
        
        if (inputValidator.containsMaliciousContent(cardNumber)) {
            log.warn("检测到恶意输入: {}", cardNumber);
            return Result.error(CodeMsgEnum.PARAM_ERROR, "输入包含非法字符");
        }

        try {
            TSysSecurity security = getSecurityConfig(ThirdServiceEnum.BANK_CARD_LOCATION.getName());
            if (security == null) {
                return Result.error(CodeMsgEnum.CONFIG_ERROR, "API配置不存在");
            }

            String url = buildV1Url(ThirdServiceEnum.BANK_CARD_LOCATION.getUrl(), cardNumber, security.getApikey());
            String responseBody = executeHttpRequest(url, null);
            
            CardBasicInfo cardInfo = JSONObject.parseObject(responseBody, CardBasicInfo.class);
            log.info("V1.0接口查询成功，卡号：{}", cardNumber);
            return Result.success(cardInfo);
            
        } catch (Exception e) {
            log.error("V1.0接口查询失败，卡号：{}，错误：{}", cardNumber, e.getMessage(), e);
            return Result.error(CodeMsgEnum.SERVICE_ERROR, "查询失败：" + e.getMessage());
        }
    }

    /**
     * 银行卡归属地查询 V2.0
     * @param request 请求参数
     * @return 银行卡基本信息
     */
    @PostMapping("/location/v2")
    public Result<CardBasicInfo> queryBankLocationV2(@RequestBody CardQueryRequest request) {
        // 输入验证
        if (request == null || !StringUtils.hasText(request.getCard())) {
            return Result.error(CodeMsgEnum.PARAM_ERROR, "银行卡号不能为空");
        }
        
        if (!inputValidator.isValidBankCard(request.getCard())) {
            log.warn("无效的银行卡号格式: {}", request.getCard());
            return Result.error(CodeMsgEnum.PARAM_ERROR, "银行卡号格式不正确");
        }
        
        if (inputValidator.containsMaliciousContent(request.getCard())) {
            log.warn("检测到恶意输入: {}", request.getCard());
            return Result.error(CodeMsgEnum.PARAM_ERROR, "输入包含非法字符");
        }

        try {
            TSysSecurity security = getSecurityConfig(ThirdServiceEnum.BANK_CARD_LOCATION.getName());
            if (security == null) {
                return Result.error(CodeMsgEnum.CONFIG_ERROR, "API配置不存在");
            }

            MultipartBody formBody = buildV2FormBody(security, request.getCard());
            String responseBody = executeHttpRequest(ThirdServiceEnum.BANK_CARD_LOCATION2.getUrl(), formBody);
            
            CardBasicInfo cardInfo = JSONObject.parseObject(responseBody, CardBasicInfo.class);
            log.info("V2.0接口查询成功，卡号：{}", request.getCard());
            return Result.success(cardInfo);
            
        } catch (Exception e) {
            log.error("V2.0接口查询失败，卡号：{}，错误：{}", request.getCard(), e.getMessage(), e);
            return Result.error(CodeMsgEnum.SERVICE_ERROR, "查询失败：" + e.getMessage());
        }
    }

    /**
     * 获取安全配置
     */
    private TSysSecurity getSecurityConfig(String serviceName) {
        LambdaQueryWrapper<TSysSecurity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TSysSecurity::getName, serviceName);
        return tSysSecurityMapper.selectOne(queryWrapper);
    }

    /**
     * 构建V1版本URL
     */
    private String buildV1Url(String baseUrl, String cardNumber, String apiKey) {
        return baseUrl + "?card=" + cardNumber + "&key=" + apiKey;
    }

    /**
     * 构建V2版本表单数据
     */
    private MultipartBody buildV2FormBody(TSysSecurity security, String cardNumber) {
        String uid = security.getUid();
        String time = LocalDateTime.now().format(DATE_FORMAT);
        String sign = DigestUtils.sha256Hex((uid + time + security.getApikey()).getBytes(StandardCharsets.UTF_8));

        return new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("uid", uid)
                .addFormDataPart("time", time)
                .addFormDataPart("sign", sign)
                .addFormDataPart("card", cardNumber)
                .build();
    }

    /**
     * 执行HTTP请求
     */
    private String executeHttpRequest(String url, MultipartBody multipartBody) throws IOException {
        Request.Builder requestBuilder = new Request.Builder().url(url);
        // 如果有表单数据，则添加到请求体中
        if (multipartBody != null) {
            requestBuilder.post(multipartBody);
        }
        
        try (Response response = okHttpClient.newCall(requestBuilder.build()).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("HTTP请求失败，状态码：" + response.code());
            }
            return Objects.requireNonNull(response.body()).string();
        }
    }
}
